package com.draven.mall.dispatch;

import com.draven.mall.entity.DispatchConfig;
import com.draven.mall.entity.Order;
import com.draven.mall.entity.Rider;
import com.draven.mall.service.DispatchConfigService;
import com.draven.mall.service.OrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.json.JSONObject;

/**
 * 综合算法实现
 * 根据距离、评分和订单数量，按权重计算综合分数，选择分数最高的骑手
 */
@Component
public class CompositeDispatchAlgorithm implements DispatchAlgorithm {

    private static final Logger log = LoggerFactory.getLogger(CompositeDispatchAlgorithm.class);

    @Autowired
    private OrderService orderService;
    
    @Autowired
    private DispatchConfigService dispatchConfigService;
    
    // 默认权重设置
    private double distanceWeight = 0.5;
    private double ratingWeight = 0.3;
    private double ordersWeight = 0.2;

    @Override
    public Rider assignRider(Order order, List<Rider> availableRiders) {
        if (availableRiders == null || availableRiders.isEmpty() || order == null) {
            return null;
        }
        
        try {
            // 加载配置的权重
            loadWeightsFromConfig();
            
            // 获取订单地址坐标
            double orderLatitude = getLatitudeFromAddress(order.getAddress());
            double orderLongitude = getLongitudeFromAddress(order.getAddress());
            
            // 计算距离分数
            Map<Long, Double> distanceScores = calculateDistanceScores(orderLatitude, orderLongitude, availableRiders);
            
            // 计算评分分数
            Map<Long, Double> ratingScores = calculateRatingScores(availableRiders);
            
            // 计算订单数量分数
            Map<Long, Double> orderCountScores = calculateOrderCountScores(availableRiders);
            
            // 计算综合分数
            Map<Long, Double> compositeScores = new HashMap<>();
            for (Rider rider : availableRiders) {
                double distanceScore = distanceScores.getOrDefault(rider.getId(), 0.0);
                double ratingScore = ratingScores.getOrDefault(rider.getId(), 0.0);
                double orderCountScore = orderCountScores.getOrDefault(rider.getId(), 0.0);
                
                double compositeScore = (distanceScore * distanceWeight) + 
                                       (ratingScore * ratingWeight) + 
                                       (orderCountScore * ordersWeight);
                
                compositeScores.put(rider.getId(), compositeScore);
            }
            
            // 找到综合分数最高的骑手
            Optional<Rider> bestRider = availableRiders.stream()
                .max(Comparator.comparingDouble(rider -> 
                    compositeScores.getOrDefault(rider.getId(), 0.0)
                ));
            
            return bestRider.orElse(null);
        } catch (Exception e) {
            log.error("计算综合分数时发生异常", e);
            return availableRiders.isEmpty() ? null : availableRiders.get(0);
        }
    }
    
    /**
     * 从配置中加载权重
     */
    private void loadWeightsFromConfig() {
        try {
            DispatchConfig config = dispatchConfigService.getActiveConfig();
            if (config != null && config.getWeightConfig() != null && !config.getWeightConfig().isEmpty()) {
                JSONObject weights = new JSONObject(config.getWeightConfig());
                
                if (weights.has("distance")) {
                    distanceWeight = weights.getDouble("distance");
                }
                
                if (weights.has("rating")) {
                    ratingWeight = weights.getDouble("rating");
                }
                
                if (weights.has("orders")) {
                    ordersWeight = weights.getDouble("orders");
                }
                
                log.info("已加载配送调度权重: 距离={}, 评分={}, 订单数={}", 
                    distanceWeight, ratingWeight, ordersWeight);
            }
        } catch (Exception e) {
            log.error("加载权重配置异常，使用默认值", e);
            // 使用默认权重
            distanceWeight = 0.5;
            ratingWeight = 0.3;
            ordersWeight = 0.2;
        }
    }
    
    /**
     * 计算距离分数（距离越近分数越高）
     */
    private Map<Long, Double> calculateDistanceScores(double orderLatitude, double orderLongitude, 
                                                   List<Rider> riders) {
        Map<Long, Double> distances = new HashMap<>();
        Map<Long, Double> scores = new HashMap<>();
        double maxDistance = 0.001; // 防止除以零
        
        // 计算每个骑手到订单的距离
        for (Rider rider : riders) {
            double riderLat = rider.getLatitude() != null ? rider.getLatitude().doubleValue() : 0;
            double riderLng = rider.getLongitude() != null ? rider.getLongitude().doubleValue() : 0;
            
            double distance = calculateDistance(orderLatitude, orderLongitude, riderLat, riderLng);
            distances.put(rider.getId(), distance);
            
            if (distance > maxDistance) {
                maxDistance = distance;
            }
        }
        
        // 计算距离分数：1 - (距离/最大距离)，确保距离越近分数越高
        for (Rider rider : riders) {
            double distance = distances.get(rider.getId());
            double score = 1 - (distance / maxDistance);
            scores.put(rider.getId(), score);
        }
        
        return scores;
    }
    
    /**
     * 计算评分分数（评分越高分数越高）
     */
    private Map<Long, Double> calculateRatingScores(List<Rider> riders) {
        Map<Long, Double> scores = new HashMap<>();
        double maxRating = 0.001; // 防止除以零
        
        // 找出最高评分
        for (Rider rider : riders) {
            float rating = rider.getRating() != null ? rider.getRating() : 0f;
            if (rating > maxRating) {
                maxRating = rating;
            }
        }
        
        // 计算评分分数：评分/最高评分
        for (Rider rider : riders) {
            float rating = rider.getRating() != null ? rider.getRating() : 0f;
            double score = rating / maxRating;
            scores.put(rider.getId(), score);
        }
        
        return scores;
    }
    
    /**
     * 计算订单数量分数（订单数量越少分数越高）
     */
    private Map<Long, Double> calculateOrderCountScores(List<Rider> riders) {
        Map<Long, Integer> orderCounts = new HashMap<>();
        Map<Long, Double> scores = new HashMap<>();
        int maxCount = 1; // 防止除以零
        
        // 获取每个骑手的配送中订单数
        for (Rider rider : riders) {
            Map<String, Object> result = orderService.getInProgressOrders(rider.getId(), 1, 100);
            int count = result != null && result.get("total") != null ? 
                    Integer.parseInt(result.get("total").toString()) : 0;
            
            orderCounts.put(rider.getId(), count);
            
            if (count > maxCount) {
                maxCount = count;
            }
        }
        
        // 计算订单数量分数：1 - (订单数/最大订单数)，确保订单数越少分数越高
        for (Rider rider : riders) {
            int count = orderCounts.get(rider.getId());
            double score = 1 - ((double) count / maxCount);
            scores.put(rider.getId(), score);
        }
        
        return scores;
    }
    
    /**
     * 计算两点之间的距离（使用简化版哈弗辛公式计算球面距离）
     */
    private double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        // 将经纬度转换为弧度
        double radLat1 = Math.toRadians(lat1);
        double radLon1 = Math.toRadians(lon1);
        double radLat2 = Math.toRadians(lat2);
        double radLon2 = Math.toRadians(lon2);
        
        // 地球半径（千米）
        double earthRadius = 6371.0;
        
        // 使用哈弗辛公式
        double dlon = radLon2 - radLon1;
        double dlat = radLat2 - radLat1;
        double a = Math.pow(Math.sin(dlat / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(dlon / 2), 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        double distance = earthRadius * c;
        
        return distance;
    }
    
    /**
     * 从地址中获取纬度（在实际应用中应通过地图API获取）
     */
    private double getLatitudeFromAddress(String address) {
        // 简单地址解析示例（实际应当接入高德/百度等地图API）
        if (address == null || address.isEmpty()) {
            return 39.908823; // 默认北京坐标
        }
        
        if (address.contains("北京")) {
            return 39.908823;
        } else if (address.contains("上海")) {
            return 31.230416;
        } else if (address.contains("广州")) {
            return 23.129163;
        } else if (address.contains("深圳")) {
            return 22.543096;
        } else if (address.contains("杭州")) {
            return 30.274085;
        } else {
            return 39.908823; // 默认北京坐标
        }
    }
    
    /**
     * 从地址中获取经度（在实际应用中应通过地图API获取）
     */
    private double getLongitudeFromAddress(String address) {
        // 简单地址解析示例（实际应当接入高德/百度等地图API）
        if (address == null || address.isEmpty()) {
            return 116.397470; // 默认北京坐标
        }
        
        if (address.contains("北京")) {
            return 116.397470;
        } else if (address.contains("上海")) {
            return 121.473701;
        } else if (address.contains("广州")) {
            return 113.264435;
        } else if (address.contains("深圳")) {
            return 114.057865;
        } else if (address.contains("杭州")) {
            return 120.155070;
        } else {
            return 116.397470; // 默认北京坐标
        }
    }

    @Override
    public int getType() {
        return 5; // 算法类型：5-综合算法
    }

    @Override
    public String getName() {
        return "综合算法";
    }
} 